from flask import Flask, jsonify, request, send_file
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
from flask_cors import CORS  # 新增：支持跨域
import datetime
import requests  # 新增：用于调用微信接口
import base64    # 新增：用于解密时的Base64解码
import json    #解析加密的JSON 数据
from Crypto.Cipher import AES  # 新增：AES解密（来自pycryptodome）

from dotenv import load_dotenv 
import os  
from sqlalchemy.exc import IntegrityError

load_dotenv()  # 加载.env文件中的环境变量

WECHAT_APP_ID = os.getenv('WECHAT_APP_ID')       # 你在.env中配置的小程序APPID
WECHAT_APP_SECRET = os.getenv('WECHAT_APP_SECRET') # 你在.env中配置的小程序密钥
WECHAT_CODE2SESSION_URL = 'https://api.weixin.qq.com/sns/jscode2session'  # 微信code换session接口

app = Flask(__name__)

# 配置CORS支持
CORS(app, resources={
    r"/api/*": {
        "origins": "*",
        "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["Content-Type", "Authorization"]
    }
})
# 配置数据库连接
# 生产环境数据库配置

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# JWT配置 - 生产环境使用更安全的密钥

app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://flask_dev:dev123456@localhost:3306/flask_local"
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = datetime.timedelta(days=int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES')))

db = SQLAlchemy(app)
jwt = JWTManager(app)

# 在 jwt = JWTManager(app) 之后添加
@jwt.expired_token_loader
def expired_token_callback(jwt_header, jwt_payload):
    return jsonify({
        'code': 401,
        'msg': 'Token已过期，请重新登录'
    }), 401

@jwt.invalid_token_loader
def invalid_token_callback(error):
    return jsonify({
        'code': 401,
        'msg': 'Token无效，请重新登录'
    }), 401

@jwt.unauthorized_loader
def missing_token_callback(error):
    return jsonify({
        'code': 401,
        'msg': '缺少Token，请先登录'
    }), 401

app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
    'pool_size': 10,           # 连接池大小
    'max_overflow': 20,        # 临时连接数
    'pool_recycle': 3600,      # 1小时后自动回收连接（防超时）
    'pool_pre_ping': True      # 连接前检查有效性
}

def wechat_code_to_openid(code):
    """
    用前端传递的code，调用微信接口换取openid和session_key
    :param code: 前端wx.login()获取的code
    :return: dict -> {'openid': '用户唯一标识', 'session_key': '解密用的密钥'}
    """
    params = {
        'appid': WECHAT_APP_ID,
        'secret': WECHAT_APP_SECRET,
        'js_code': code,
        'grant_type': 'authorization_code'
    }
    try:
        response = requests.get(WECHAT_CODE2SESSION_URL, params=params, timeout=10)
        response.raise_for_status()  # 新增：触发HTTP错误（如404/500）
        result = response.json()
        # 处理微信接口错误（如code过期、appid错误）
        if 'errcode' in result and result['errcode'] != 0:
            raise Exception(f"微信接口错误[{result['errcode']}]: {result.get('errmsg', '未知错误')}")
        # 检查是否返回openid
        if not result.get('openid'):
            raise Exception("未获取到openid")
        return {
            'openid': result['openid'],
            'session_key': result.get('session_key')  # session_key用于解密encryptedData
        }
    except requests.exceptions.HTTPError as e:
        raise Exception(f"微信接口HTTP错误: {str(e)}")  # 新增：捕获HTTP错误
    except requests.exceptions.RequestException as e:
        raise Exception(f"请求微信服务器失败: {str(e)}")  # 捕获超时/连接错误
    except Exception as e:
        raise Exception(f"code换openid失败: {str(e)}")

def decrypt_wechat_encrypted_data(encrypted_data, iv, session_key):
    try:
        # 1. Base64解码
        session_key = base64.b64decode(session_key)
        encrypted_data = base64.b64decode(encrypted_data)
        iv = base64.b64decode(iv)
        
        # 2. AES解密
        cipher = AES.new(session_key, AES.MODE_CBC, iv)
        decrypted_bytes = cipher.decrypt(encrypted_data)
        
        # 3. 修复：先判断解密后的数据是否为空
        if not decrypted_bytes:
            raise Exception("解密后数据为空")
        # 去除PKCS#7填充
        unpad = lambda s: s[:-ord(s[len(s)-1:])]
        decrypted_str = unpad(decrypted_bytes).decode('utf-8')
        
        # 4. 解析JSON并验证appid
        decrypted_data = json.loads(decrypted_str)
        if decrypted_data['watermark']['appid'] != WECHAT_APP_ID:
            raise Exception("解密数据非法：appid不匹配")
        
        return decrypted_data
    except Exception as e:
        raise Exception(f"解密encryptedData失败: {str(e)}")

# 数据模型定义 - 映射数据库表
class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    openid = db.Column(db.String(64), unique=True, nullable=True)  # 允许为空：医生创建的患者没有openid
    wechat_name = db.Column(db.String(32), nullable=True)  # 改为允许为空（用户可能拒绝授权昵称）
    wechat_avatar = db.Column(db.String(255), nullable=True)  # 允许为空（用户可能拒绝授权头像）
    phone = db.Column(db.String(11), unique=True, nullable=True)  # 改为允许为空（登录时无需手机号）
    # real_name 字段已删除，真实姓名存储在 user_doctor/user_patient 表中
    role = db.Column(db.Integer, nullable=False, default=0)  # 新增默认值0（未指定角色）
    status = db.Column(db.Integer, default=1)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now)  # 修复：移除括号，确保每条记录使用创建时的时间
    update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)  # 修复：移除括号

class UserDoctor(db.Model):
    __tablename__ = 'user_doctor'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    real_name = db.Column(db.String(32), nullable=False)  # 真实姓名
    hospital = db.Column(db.String(64), nullable=False)
    department = db.Column(db.String(32), nullable=False)
    position = db.Column(db.String(32), nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now)  # 修复：移除括号
    update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)  # 修复：移除括号

class UserPatient(db.Model):
    __tablename__ = 'user_patient'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    real_name = db.Column(db.String(32), nullable=False)  # 真实姓名
    gender = db.Column(db.Integer, nullable=False)
    age = db.Column(db.Integer, nullable=False)
    id_card = db.Column(db.String(18), unique=True, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now)  # 修复：移除括号
    update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)  # 修复：移除括号

# 新增：医生-患者绑定关系表（存储医生绑定的患者）
class DoctorPatientBind(db.Model):
    __tablename__ = 'doctor_patient_bind'  
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  
    doctor_id = db.Column(db.Integer, nullable=False)  
    patient_id = db.Column(db.Integer, nullable=False)  
  
    bind_time = db.Column(db.DateTime, default=datetime.datetime.now, nullable=False)  # 修复：移除括号
   
    status = db.Column(db.Integer, default=1, nullable=False)

    # 1. 联合唯一约束：与数据库的_unique_doctor_patient_unique约束名完全一致
    # 2. 外键约束：与数据库的外键配置一致（确保关联user表id，级联删除）
    __table_args__ = (
        db.UniqueConstraint('doctor_id', 'patient_id', name='_doctor_patient_unique'),
        db.ForeignKeyConstraint(['doctor_id'], ['user.id'], ondelete='CASCADE'),
        db.ForeignKeyConstraint(['patient_id'], ['user.id'], ondelete='CASCADE'),
    )

class ScaleAssessment(db.Model):
    __tablename__ = 'scale_assessment'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    assessor_id = db.Column(db.Integer, nullable=False)
    assessment_type = db.Column(db.Integer, nullable=False, default=1)  # 评估类型: 1-医生评估, 2-患者自评
    assessment_date = db.Column(db.Date, nullable=False)
    hamd_total = db.Column(db.Integer, nullable=False)
    hamd_status = db.Column(db.Integer, nullable=False, default=0)  # HAMD完成状态: 0-未填写, 1-已完成
    hama_total = db.Column(db.Integer, nullable=False)
    hama_status = db.Column(db.Integer, nullable=False, default=0)  # HAMA完成状态: 0-未填写, 1-已完成
    ymrs_total = db.Column(db.Integer, nullable=False)
    ymrs_status = db.Column(db.Integer, nullable=False, default=0)  # YMRS完成状态: 0-未填写, 1-已完成
    assessment_notes = db.Column(db.Text)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now)  # 修复：移除括号
    update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)  # 修复：移除括号

class ScaleHama(db.Model):
    """HAMA焦虑量表模型（对应 scale_hama 表）"""
    __tablename__ = 'scale_hama'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_irritability = db.Column(db.Integer, nullable=False)  # 易激惹
    item2_tension = db.Column(db.Integer, nullable=False)  # 紧张
    item3_fears = db.Column(db.Integer, nullable=False)  # 害怕
    item4_insomnia = db.Column(db.Integer, nullable=False)  # 失眠
    item5_cognition = db.Column(db.Integer, nullable=False)  # 认知功能
    item6_depressed_mood = db.Column(db.Integer, nullable=False)  # 抑郁心境
    item7_somatic_muscle = db.Column(db.Integer, nullable=False)  # 躯体性肌肉症状
    item8_somatic_sensory = db.Column(db.Integer, nullable=False)  # 躯体性感觉症状
    item9_cardiovascular = db.Column(db.Integer, nullable=False)  # 心血管系统症状
    item10_respiratory = db.Column(db.Integer, nullable=False)  # 呼吸系统症状
    item11_gastrointestinal = db.Column(db.Integer, nullable=False)  # 胃肠道症状
    item12_genitourinary = db.Column(db.Integer, nullable=False)  # 泌尿生殖系统症状
    item13_autonomic = db.Column(db.Integer, nullable=False)  # 自主神经症状
    item14_behavior = db.Column(db.Integer, nullable=False)  # 行为表现


class ScaleHamd17(db.Model):
    """HAMD17抑郁量表模型（对应 scale_hamd17 表）"""
    __tablename__ = 'scale_hamd17'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_depression = db.Column(db.Integer, nullable=False)  # 抑郁情绪
    item2_guilt = db.Column(db.Integer, nullable=False)  # 罪恶感
    item3_suicide = db.Column(db.Integer, nullable=False)  # 自杀
    item4_sleep_initial = db.Column(db.Integer, nullable=False)  # 入睡困难
    item5_sleep_middle = db.Column(db.Integer, nullable=False)  # 睡眠不深
    item6_sleep_late = db.Column(db.Integer, nullable=False)  # 早醒
    item7_activity = db.Column(db.Integer, nullable=False)  # 工作和兴趣
    item8_retardation = db.Column(db.Integer, nullable=False)  # 迟滞
    item9_agitation = db.Column(db.Integer, nullable=False)  # 激越
    item10_anxiety_psychic = db.Column(db.Integer, nullable=False)  # 精神性焦虑
    item11_anxiety_somatic = db.Column(db.Integer, nullable=False)  # 躯体性焦虑
    item12_somatic_symptoms = db.Column(db.Integer, nullable=False)  # 胃肠道症状
    item13_general_somatic = db.Column(db.Integer, nullable=False)  # 全身症状
    item14_genital = db.Column(db.Integer, nullable=False)  # 性症状
    item15_hypochondriasis = db.Column(db.Integer, nullable=False)  # 疑病
    item16_weight = db.Column(db.Integer, nullable=False)  # 体重减轻
    item17_insight = db.Column(db.Integer, nullable=False)  # 自知力


class ScaleYmrs(db.Model):
    """YMRS躁狂量表模型（对应 scale_ymrs 表）"""
    __tablename__ = 'scale_ymrs'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_mood_elevated = db.Column(db.Integer, nullable=False)  # 情绪高涨
    item2_activity = db.Column(db.Integer, nullable=False)  # 活动增多
    item3_sleep = db.Column(db.Integer, nullable=False)  # 睡眠减少
    item4_irritability = db.Column(db.Integer, nullable=False)  # 易激惹
    item5_speech_rate = db.Column(db.Integer, nullable=False)  # 言语速度和量
    item6_speech_pressured = db.Column(db.Integer, nullable=False)  # 言语迫促
    item7_thought_content = db.Column(db.Integer, nullable=False)  # 思维内容
    item8_grandiosity = db.Column(db.Integer, nullable=False)  # 夸大
    item9_distractibility = db.Column(db.Integer, nullable=False)  # 随境转移
    item10_hostility = db.Column(db.Integer, nullable=False)  # 敌意
    item11_grandiosity_severity = db.Column(db.Integer, nullable=False)  # 夸大严重程度


# 认证接口
# 认证接口（改造后：支持接收wx.getUserProfile的用户信息）
@app.route('/api/v1/auth/login', methods=['POST'])
def login():
    try:
        # 1. 接收前端传递的参数（包含code、用户信息、加密数据）
        data = request.get_json()
        code = data.get('code')  # 前端wx.login()获取的code（必选）
        user_info = data.get('user_info', {})  # 前端wx.getUserProfile()获取的明文信息（如昵称、头像）
        encrypted_data = data.get('encrypted_data')  # 前端传递的加密信息（可选，用于获取unionId）
        iv = data.get('iv')  # 前端传递的解密向量（可选，与encrypted_data配套）

        # 2. 校验必填参数
        if not code:
            return jsonify({'code': 400, 'msg': '缺少code参数'})

        # 3. 调用微信接口，用code换取openid和session_key
        wechat_result = wechat_code_to_openid(code)
        openid = wechat_result['openid']
        session_key = wechat_result.get('session_key')

        # 4. （可选）解密encrypted_data，获取unionId（多小程序/公众号统一用户标识）
        union_id = None
        if encrypted_data and iv and session_key:
            decrypted_data = decrypt_wechat_encrypted_data(encrypted_data, iv, session_key)
            union_id = decrypted_data.get('unionId')  # 提取unionId（如需存储，需在User模型新增union_id字段）

        # 5. 查询/创建用户，并更新微信信息
        user = User.query.filter_by(openid=openid).first()
        if not user:
            # 5.1 新建用户：用wx.getUserProfile的信息填充
            user = User(
                openid=openid,
                wechat_name=user_info.get('nickName', ''),  # 微信昵称（明文）
                wechat_avatar=user_info.get('avatarUrl', ''),  # 微信头像URL（明文）
                phone=None,  # 修复：使用None避免空字符串冲突
                role=0,  # 默认角色0（未指定角色）
                create_time=datetime.datetime.now(),
                update_time=datetime.datetime.now()
            )
            db.session.add(user)
        else:
            # 5.2 已有用户：更新微信信息（用户可能修改了微信昵称/头像）
            if user_info.get('nickName'):
                user.wechat_name = user_info.get('nickName')
            if user_info.get('avatarUrl'):
                user.wechat_avatar = user_info.get('avatarUrl')
            # update_time由模型onupdate自动更新

        # 6. 提交数据库
        db.session.commit()

        # 7. 生成JWT Token，返回结果给前端（修复：identity转换为字符串）
        access_token = create_access_token(identity=str(user.id))
        return jsonify({
            'code': 200,
            'msg': '登录成功',
            'data': {
                'token': access_token,
                'user_id': user.id,
                'role': user.role,
                'user_info': {  # 返回用户信息，前端可直接显示（避免二次请求）
                    'wechat_name': user.wechat_name,  # nickname
                    'wechat_avatar': user.wechat_avatar,  # avatar
                    # 不返回 real_name，因为登录时用户还没有填写真实姓名
                }
            }
        })

    # 8. 异常处理（分类返回错误信息，便于调试）
    except requests.exceptions.RequestException as e:
        return jsonify({'code': 500, 'msg': f'请求微信服务器失败: {str(e)}'})
    except Exception as e:
        db.session.rollback()  # 数据库回滚，防止脏数据
        return jsonify({'code': 500, 'msg': f'登录失败: {str(e)}'})

# 发送验证码接口（开发环境：固定验证码123456）
@app.route('/api/v1/auth/send-sms', methods=['POST'])
def send_sms_code():
    """
    发送验证码（开发环境：直接返回固定验证码123456）
    生产环境可替换为真实短信服务
    """
    try:
        data = request.get_json()
        phone = data.get('phone')
        
        if not phone:
            return jsonify({'code': 400, 'msg': '请输入手机号'})
        
        # 手机号格式验证
        import re
        if not re.match(r'^1[3-9]\d{9}$', phone):
            return jsonify({'code': 400, 'msg': '手机号格式不正确'})
        
        # 开发环境：直接返回成功，验证码固定为 123456
        print(f'[DEV] 手机号 {phone} 的验证码是: 123456')
        
        return jsonify({
            'code': 200,
            'msg': '验证码发送成功',
            'data': {
                'dev_code': '123456',  # 仅开发环境返回，方便测试
                'expires_in': 300  # 5分钟有效期（实际未实现）
            }
        })
        
    except Exception as e:
        print(f'[ERROR] 发送验证码失败: {str(e)}')
        return jsonify({'code': 500, 'msg': f'发送失败：{str(e)}'})


# 验证码登录接口
@app.route('/api/v1/auth/sms-login', methods=['POST'])
def sms_login():
    """
    手机验证码登录
    - 开发环境：验证码固定为123456
    - 如果手机号已注册：直接登录
    - 如果手机号未注册：返回need_register标记
    """
    try:
        data = request.get_json()
        phone = data.get('phone')
        code = data.get('code')
        
        if not phone or not code:
            return jsonify({'code': 400, 'msg': '请输入手机号和验证码'})
        
        # 开发环境：验证码固定为 123456
        if code != '123456':
            return jsonify({'code': 400, 'msg': '验证码错误'})
        
        # 查找用户（手机号 + 状态正常）
        user = User.query.filter_by(phone=phone, status=1).first()
        
        if not user:
            # 手机号未注册
            print(f'[INFO] 手机号 {phone} 未注册')
            return jsonify({
                'code': 201,
                'msg': '手机号未注册',
                'data': {
                    'need_register': True,
                    'phone': phone
                }
            })
        
        # 用户已注册，生成token并返回
        access_token = create_access_token(identity=str(user.id))
        
        # 构建用户信息（包含详细信息）
        user_data = {
            'id': user.id,
            'phone': user.phone,
            'wechat_name': user.wechat_name,
            'wechat_avatar': user.wechat_avatar,
            'role': user.role
        }
        
        # 如果是患者，获取患者详细信息（获取最新的一条记录）
        if user.role == 2:
            patient_info = UserPatient.query.filter_by(user_id=user.id).order_by(UserPatient.create_time.desc()).first()
            if patient_info:
                user_data.update({
                    'real_name': patient_info.real_name,
                    'gender': patient_info.gender,
                    'age': patient_info.age,
                    'id_card': patient_info.id_card
                })
        
        print(f'[OK] 用户[{user.id}] 通过验证码登录成功: {phone}')
        
        return jsonify({
            'code': 200,
            'msg': '登录成功',
            'data': {
                'token': access_token,
                'user': user_data
            }
        })
        
    except Exception as e:
        print(f'[ERROR] 验证码登录失败: {str(e)}')
        return jsonify({'code': 500, 'msg': f'登录失败：{str(e)}'})


# 获取当前用户信息
@app.route('/api/v1/auth/user-info', methods=['GET'])
@jwt_required()
def get_user_info():
    user_id = get_jwt_identity()
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})
    
    user_info = {
        'id': user.id,
        'wechat_name': user.wechat_name,  # nickname（微信昵称）
        'wechat_avatar': user.wechat_avatar,  # avatar（微信头像）
        'phone': user.phone,
        'role': user.role,
        'status': user.status,
        'create_time': user.create_time.strftime('%Y-%m-%d %H:%M:%S')
    }
    
    # 如果是医生，获取医生详细信息（获取最新的一条记录）
    if user.role == 1:
        doctor_info = UserDoctor.query.filter_by(user_id=user_id).order_by(UserDoctor.create_time.desc()).first()
        if doctor_info:
            user_info.update({
                'real_name': doctor_info.real_name,
                'hospital': doctor_info.hospital,
                'department': doctor_info.department,
                'position': doctor_info.position
            })
    
    # 如果是患者，获取患者详细信息（获取最新的一条记录）
    elif user.role == 2:
        patient_info = UserPatient.query.filter_by(user_id=user_id).order_by(UserPatient.create_time.desc()).first()
        if patient_info:
            user_info.update({
                'real_name': patient_info.real_name,
                'gender': patient_info.gender,
                'age': patient_info.age,
                'id_card': patient_info.id_card
            })
    
    return jsonify({
        'code': 200,
        'data': user_info
    })

# 获取指定用户信息
@app.route('/api/v1/users/<int:user_id>', methods=['GET'])
@jwt_required()
def get_user_by_id(user_id):
    try:
        # 获取用户基础信息
        user = User.query.get(user_id)
        if not user:
            return jsonify({'code': 404, 'msg': '用户不存在'})
        
        # 根据用户角色获取详细信息
        user_info = {
            'id': user.id,
            'wechat_name': user.wechat_name,
            'wechat_avatar': user.wechat_avatar,
            'phone': user.phone,
            'role': user.role,
            'status': user.status
        }
        
        # 如果是医生，获取医生详细信息（获取最新的一条记录）
        if user.role == 1:
            doctor_info = UserDoctor.query.filter_by(user_id=user_id).order_by(UserDoctor.create_time.desc()).first()
            if doctor_info:
                user_info.update({
                    'real_name': doctor_info.real_name,
                    'hospital': doctor_info.hospital,
                    'department': doctor_info.department,
                    'position': doctor_info.position
                })
        
        # 如果是患者，获取患者详细信息（获取最新的一条记录）
        elif user.role == 2:
            patient_info = UserPatient.query.filter_by(user_id=user_id).order_by(UserPatient.create_time.desc()).first()
            if patient_info:
                user_info.update({
                    'real_name': patient_info.real_name,
                    'gender': patient_info.gender,
                    'age': patient_info.age,
                    'id_card': patient_info.id_card
                })
        
        return jsonify({
            'code': 200,
            'data': user_info
        })
        
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'获取用户信息失败：{str(e)}'})

# 完善用户信息接口（如绑定手机号、选择角色）
@app.route('/api/v1/auth/complete-info', methods=['POST'])
@jwt_required()
def complete_user_info():
    try:
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        if not user:
            return jsonify({'code': 404, 'msg': '用户不存在'})
        
        data = request.get_json()
        phone = data.get('phone')  # 用户填写的手机号
        role = data.get('role')    # 用户选择的角色（1=医生，2=患者）

        # 校验参数
        if not phone or role not in [1, 2]:  # 修复：调整运算符优先级
            return jsonify({'code': 400, 'msg': '缺少手机号或角色选择错误'})
        
        # 检查手机号是否已被占用
        if User.query.filter_by(phone=phone).first() and User.query.filter_by(phone=phone).first().id != user_id:
            return jsonify({'code': 400, 'msg': '手机号已被绑定'})
        
        # 更新用户信息
        user.phone = phone
        user.role = role
        # update_time由模型onupdate自动更新
        db.session.commit()

        return jsonify({'code': 200, 'msg': '信息完善成功', 'data': {'role': user.role}})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'完善信息失败: {str(e)}'})

# 医生信息接口
@app.route('/api/v1/users/doctor', methods=['POST'])
@jwt_required()
def create_doctor_info():
    user_id = get_jwt_identity()
    data = request.get_json()
    
    # 验证用户是否存在
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})

     # 新增：校验用户角色是否为医生，避免重复创建
    if user.role != 1:
        return jsonify({'code': 403, 'msg': '仅医生角色可完善医生信息'})
    
    # 更新用户基础信息
    user.phone = data['phone']
    # 不存储 real_name 到 user 表，因为真实姓名应该存储在 user_doctor 表中
    
    # 查询是否已有医生信息（获取最新的一条）
    existing_doctor = UserDoctor.query.filter_by(user_id=user_id).order_by(UserDoctor.create_time.desc()).first()
    
    if existing_doctor:
        # 如果已存在，更新现有记录
        existing_doctor.real_name = data['real_name']
        existing_doctor.hospital = data.get('hospital')
        existing_doctor.department = data.get('department')
        existing_doctor.position = data.get('position')
        existing_doctor.update_time = datetime.datetime.now()
        
        db.session.commit()
        
        print(f'[OK] 医生[{user_id}]更新信息成功: name={data["real_name"]}, hospital={data.get("hospital")}')
        
        return jsonify({
            'code': 200,
            'msg': '医生信息更新成功',
            'data': {'id': existing_doctor.id}
        })
    else:
        # 如果不存在，创建新记录
        doctor = UserDoctor(
            user_id=user_id,
            real_name=data['real_name'],
            hospital=data.get('hospital'),
            department=data.get('department'),
            position=data.get('position'),
        )
        db.session.add(doctor)
        db.session.commit()
        
        print(f'[OK] 医生[{user_id}]创建信息成功: name={data["real_name"]}, hospital={data.get("hospital")}')
        
        return jsonify({
            'code': 200,
            'msg': '医生信息创建成功',
            'data': {'id': doctor.id}
        })

# 1. 用户管理模块 - 医生信息接口（续）
# ------------------------------
# 1.1 获取当前登录医生的详情（医生查看自己的信息）
@app.route('/api/v1/users/doctor/self', methods=['GET'])
@jwt_required()
def get_self_doctor_info():
    user_id = get_jwt_identity()
    # 1. 验证用户是否为医生角色
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})
    if user.role != 1:  # 1=医生角色
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 查询医生详情（获取最新的一条记录）
    doctor_info = UserDoctor.query.filter_by(user_id=user_id).order_by(UserDoctor.create_time.desc()).first()
    if not doctor_info:
        return jsonify({'code': 404, 'msg': '医生信息未完善'})
    
    # 3. 构造返回数据
    return jsonify({
        'code': 200,
        'data': {
            'user_id': doctor_info.user_id,
            'real_name': doctor_info.real_name,  # 添加真实姓名
            'hospital': doctor_info.hospital,
            'department': doctor_info.department,
            'position': doctor_info.position,
            'create_time': doctor_info.create_time.strftime('%Y-%m-%d %H:%M:%S'),
            'update_time': doctor_info.update_time.strftime('%Y-%m-%d %H:%M:%S')
        }
    })

# 1.2 更新医生信息（医生修改自己的信息）

@app.route('/api/v1/users/doctor/self', methods=['PUT'])
@jwt_required()
def update_self_doctor_info():
    user_id = get_jwt_identity()
    data = request.get_json()

    # 1. 验证用户身份
    user = User.query.get(user_id)
    if not user or user.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})

    # 2. 查询医生信息（获取最新的一条记录）
    doctor_info = UserDoctor.query.filter_by(user_id=user_id).order_by(UserDoctor.create_time.desc()).first()
    if not doctor_info:
        return jsonify({'code': 404, 'msg': '医生信息未完善，无法更新'})

    # 3. 更新字段（只更新传入的非空字段）
    if 'hospital' in data and data['hospital']:
        doctor_info.hospital = data['hospital']
    if 'department' in data and data['department']:
        doctor_info.department = data['department']
    if 'position' in data and data['position']:
        doctor_info.position = data['position']
    doctor_info.update_time = datetime.datetime.now()  # 调用datetime类的now方法

    # 4. 提交事务
    try:
        db.session.commit()
        return jsonify({'code': 200, 'msg': '医生信息更新成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'更新失败：{str(e)}'})

# 1.3 管理员查询指定医生信息（需管理员权限）
@app.route('/api/v1/admin/doctors/<int:doctor_user_id>', methods=['GET'])
@jwt_required()
def admin_get_doctor(doctor_user_id):
    admin_id = get_jwt_identity()
    # 1. 验证管理员身份
    admin = User.query.get(admin_id)
    if not admin or admin.role != 3:  # 3=管理员角色
        return jsonify({'code': 403, 'msg': '权限不足，非管理员'})
    
    # 2. 查询医生信息（获取最新的一条记录）
    doctor_info = UserDoctor.query.filter_by(user_id=doctor_user_id).order_by(UserDoctor.create_time.desc()).first()
    doctor_base = User.query.get(doctor_user_id)
    if not doctor_base or not doctor_info:
        return jsonify({'code': 404, 'msg': '医生不存在'})
    
    return jsonify({
        'code': 200,
        'data': {
            'user_id': doctor_user_id,
            'wechat_name': doctor_base.wechat_name,  # 微信昵称
            'wechat_avatar': doctor_base.wechat_avatar,  # 头像
            'real_name': doctor_info.real_name,  # 真实姓名存储在 user_doctor 表中
            'phone': doctor_base.phone,
            'hospital': doctor_info.hospital,
            'department': doctor_info.department,
            'position': doctor_info.position,
            'status': doctor_base.status  # 账号状态（1=正常，0=禁用）
        }
    })


# ------------------------------

# 医生创建患者完整账号（包含user记录 + user_patient记录 + 自动绑定）
@app.route('/api/v1/doctor/create-patient-account', methods=['POST'])
@jwt_required()
def doctor_create_patient_account():
    """
    医生创建患者完整账号（新增功能）
    - 创建user基础记录（role=2）
    - 创建user_patient详细信息
    - 自动绑定到当前医生
    - 患者无需密码（使用验证码登录）
    """
    try:
        doctor_id = get_jwt_identity()
        data = request.get_json()
        
        # 1. 验证医生身份
        doctor = User.query.get(doctor_id)
        if not doctor or doctor.role != 1:
            return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
        
        # 2. 验证必填参数
        required_fields = ['phone', 'real_name', 'gender', 'age', 'id_card']
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
        
        phone = data['phone']
        real_name = data['real_name']
        gender = int(data['gender'])
        age = int(data['age'])
        id_card = data['id_card']
        
        # 3. 检查手机号是否已存在
        existing_user = User.query.filter_by(phone=phone, status=1).first()
        if existing_user:
            return jsonify({'code': 400, 'msg': '该手机号已注册，请直接搜索绑定'})
        
        # 4. 检查身份证号是否已存在
        existing_patient = UserPatient.query.filter_by(id_card=id_card).first()
        if existing_patient:
            return jsonify({'code': 400, 'msg': '该身份证号已存在'})
        
        # 5. 创建user基础记录（openid=NULL，因为是医生创建的）
        new_user = User(
            phone=phone,
            role=2,  # 患者角色
            openid=None,  # 医生创建时不需要openid
            wechat_name=real_name,  # 暂时用真实姓名填充
            status=1
        )
        db.session.add(new_user)
        db.session.flush()  # 获取new_user.id
        
        # 6. 创建user_patient详细信息
        new_patient = UserPatient(
            user_id=new_user.id,
            real_name=real_name,
            gender=gender,
            age=age,
            id_card=id_card
        )
        db.session.add(new_patient)
        
        # 7. 自动绑定到当前医生
        bind_record = DoctorPatientBind(
            doctor_id=doctor_id,
            patient_id=new_user.id,
            status=1
        )
        db.session.add(bind_record)
        
        # 8. 提交事务
        db.session.commit()
        
        print(f'[OK] 医生[{doctor_id}]成功创建患者账号: user_id={new_user.id}, phone={phone}, name={real_name}')
        
        return jsonify({
            'code': 200,
            'msg': '患者账号创建成功并已自动绑定',
            'data': {
                'patient_user_id': new_user.id,
                'patient_detail_id': new_patient.id,
                'auto_bound': True
            }
        })
        
    except IntegrityError as e:
        db.session.rollback()
        print(f'[ERROR] 创建患者账号失败（数据重复）: {str(e)}')
        return jsonify({'code': 400, 'msg': '手机号或身份证号已被使用'})
    except Exception as e:
        db.session.rollback()
        print(f'[ERROR] 创建患者账号失败: {str(e)}')
        return jsonify({'code': 500, 'msg': f'创建失败：{str(e)}'})


@app.route('/api/v1/users/patient', methods=['POST'])
@jwt_required()
def create_patient_info():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证医生身份
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 验证必填参数
    required_fields = ['user_id', 'gender', 'age', 'id_card']
    for field in required_fields:
        if field not in data or not data[field]:
            return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
    
    # 3. 验证患者基础信息存在（修复：先判断是否为None）
    patient_base = User.query.get(data['user_id'])
    if not patient_base:
        return jsonify({'code': 404, 'msg': '患者基础信息不存在'})
    # 只有患者存在时，才判断角色
    if patient_base.role != 2:
        patient_base.role = 2
        # 修复：用模型默认的update_time自动更新，无需手动传值
        # patient_base.update_time = datetime.datetime.now()
    
    # 4. 更新用户基础信息
    patient_base.phone = data['phone']
    # 不存储 real_name 到 user 表，因为真实姓名应该存储在 user_patient 表中
    # 保留微信昵称（不覆盖），前端可根据需要选择显示哪个
    # patient_base.wechat_name = data['real_name']  # 注释掉这行，避免覆盖微信昵称
    
    # 5. 创建患者详情（修复：添加必填的 real_name 字段）
    try:
        patient_info = UserPatient(
            user_id=data['user_id'],
            real_name=data.get('real_name', '未填写'),  # 修复：添加必填字段
            gender=data['gender'],
            age=data['age'],
            id_card=data['id_card']
        )
        db.session.add(patient_info)
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': '患者信息创建成功',
            'data': {'patient_id': patient_info.id}
        })
    except IntegrityError:
        db.session.rollback()
        return jsonify({'code': 400, 'msg': '身份证号已存在'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'创建失败：{str(e)}'})

# 患者自主建档接口
@app.route('/api/v1/users/patient/self-register', methods=['POST'])
@jwt_required()
def patient_self_register():
    """患者自主完善个人档案"""
    try:
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        # 验证是患者角色
        if not user or user.role != 2:
            return jsonify({'code': 403, 'msg': '仅患者可自主建档'})
        
        # 检查是否已建档（获取最新的一条记录）
        existing = UserPatient.query.filter_by(user_id=user_id).order_by(UserPatient.create_time.desc()).first()
        
        data = request.get_json()
        required = ['gender', 'age', 'id_card', 'real_name']
        for field in required:
            if field not in data:
                return jsonify({'code': 400, 'msg': f'缺少必填字段：{field}'})
        
        # 更新用户基础信息
        user.phone = data.get('phone', user.phone)
        # 不存储 real_name 到 user 表，因为真实姓名应该存储在 user_patient 表中
        
        if existing:
            # 档案已存在，更新信息
            print(f'[患者建档] 患者[{user_id}]档案已存在，更新信息')
            print(f'   - 旧姓名: {existing.real_name} -> 新姓名: {data["real_name"]}')
            
            existing.real_name = data['real_name']
            existing.gender = data['gender']
            existing.age = data['age']
            existing.id_card = data['id_card']
            existing.update_time = datetime.datetime.now()
            db.session.commit()
            
            return jsonify({
                'code': 200,
                'msg': '档案更新成功',
                'data': {'patient_id': existing.id}
            })
        else:
            # 创建新的患者档案
            print(f'[患者建档] 患者[{user_id}]创建新档案')
            print(f'   - 姓名: {data["real_name"]}')
            
            patient = UserPatient(
                user_id=user_id,
                real_name=data['real_name'],
                gender=data['gender'],
                age=data['age'],
                id_card=data['id_card']
            )
            db.session.add(patient)
            db.session.commit()
            
            return jsonify({
                'code': 200,
                'msg': '建档成功',
                'data': {'patient_id': patient.id}
            })
    except IntegrityError:
        db.session.rollback()
        return jsonify({'code': 400, 'msg': '身份证号已被使用'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'建档失败：{str(e)}'})

# 患者更新档案接口
@app.route('/api/v1/users/patient/update-profile', methods=['PUT'])
@jwt_required()
def patient_update_profile():
    """患者更新个人档案"""
    try:
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        # 验证是患者角色
        if not user or user.role != 2:
            return jsonify({'code': 403, 'msg': '仅患者可更新档案'})
        
        # 获取最新的患者档案
        patient_info = UserPatient.query.filter_by(user_id=user_id).order_by(UserPatient.create_time.desc()).first()
        if not patient_info:
            return jsonify({'code': 404, 'msg': '患者档案不存在，请先建档'})
        
        data = request.get_json()
        
        # 更新字段（只更新传入的非空字段）
        if 'real_name' in data and data['real_name']:
            patient_info.real_name = data['real_name']
            print(f'[更新档案] 患者[{user_id}]更新姓名: {data["real_name"]}')
        
        if 'gender' in data and data['gender'] is not None:
            patient_info.gender = data['gender']
        
        if 'age' in data and data['age']:
            patient_info.age = data['age']
        
        if 'id_card' in data and data['id_card']:
            # 检查身份证号是否被其他患者使用
            existing_patient = UserPatient.query.filter(
                UserPatient.id_card == data['id_card'],
                UserPatient.user_id != user_id
            ).first()
            if existing_patient:
                return jsonify({'code': 400, 'msg': '该身份证号已被其他患者使用'})
            patient_info.id_card = data['id_card']
        
        if 'phone' in data and data['phone']:
            user.phone = data['phone']
        
        patient_info.update_time = datetime.datetime.now()
        db.session.commit()
        
        print(f'[更新档案] 患者[{user_id}]档案更新成功')
        
        return jsonify({
            'code': 200,
            'msg': '档案更新成功',
            'data': {
                'patient_id': patient_info.id,
                'real_name': patient_info.real_name
            }
        })
    except IntegrityError as e:
        db.session.rollback()
        print(f'[更新档案] 数据库约束错误: {str(e)}')
        return jsonify({'code': 400, 'msg': '身份证号或手机号已被使用'})
    except Exception as e:
        db.session.rollback()
        print(f'[更新档案] 更新失败: {str(e)}')
        return jsonify({'code': 500, 'msg': f'更新失败：{str(e)}'})

# ------------------------------
# 3. 量表评估模块 - 评估记录接口
# ------------------------------
# 3.1 医生创建患者评估记录（主记录）- 新增绑定校验
@app.route('/api/v1/assessments', methods=['POST'])
@jwt_required()
def create_assessment():
    current_user_id = get_jwt_identity()
    current_user = User.query.get(current_user_id)
    data = request.get_json()
    
    print(f"=== create_assessment 调试信息 ===")
    print(f"current_user_id: {current_user_id}")
    print(f"current_user: {current_user}")
    print(f"data: {data}")
    
    if not current_user:
        return jsonify({'code': 403, 'msg': '用户不存在'})
    
    # 验证必填参数
    required_fields = ['user_id', 'assessment_date']
    for field in required_fields:
        if field not in data or not data[field]:
            return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
    
    # 权限检查：医生可以为任何患者创建，患者只能为自己创建
    if current_user.role == 1:  # 医生
        # 医生可以为任何患者创建评估记录
        # 检查医生是否已绑定该患者
        patient_id = data['user_id']
        is_bound = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == current_user_id,
            DoctorPatientBind.patient_id == patient_id,
            DoctorPatientBind.status == 1
        ).first()
        if not is_bound:
            return jsonify({'code': 403, 'msg': '未绑定该患者，请先绑定再创建评估记录'})
        
        # 验证患者存在
        if not User.query.get(patient_id) or User.query.get(patient_id).role != 2:
            return jsonify({'code': 404, 'msg': '患者不存在'})
            
    elif current_user.role == 2:  # 患者
        # 患者只能为自己创建评估记录（统一转为整型再比较，避免 '2' 与 2 的类型不一致）
        try:
            req_user_id = int(data.get('user_id'))
            cur_user_id = int(current_user_id)
        except (TypeError, ValueError):
            return jsonify({'code': 400, 'msg': '无效的用户ID'})
        if cur_user_id != req_user_id:
            print(f"患者ID不匹配: current_user_id={current_user_id}, data['user_id']={data.get('user_id')}")
            return jsonify({'code': 403, 'msg': '只能为自己创建评估记录'})
        print(f"患者自评：current_user_id={current_user_id}, data['user_id']={data.get('user_id')}")
    else:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 验证分数字段（允许为0，但不能为None或空字符串）
    score_fields = ['hamd_total', 'hama_total', 'ymrs_total']
    for field in score_fields:
        if field not in data or data[field] is None:
            return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
        # 确保分数是数字类型
        try:
            data[field] = int(data[field])
        except (ValueError, TypeError):
            return jsonify({'code': 400, 'msg': f'{field}必须是有效的数字'})
    
    # 验证分数范围（防止异常值）
    for field in score_fields:
        if data[field] < 0 or data[field] > 100:  # 假设最大分数为100
            return jsonify({'code': 400, 'msg': f'{field}分数超出有效范围(0-100)'})
    
    # 7. 创建评估记录
    try:
        # 转换日期格式（前端传 'YYYY-MM-DD'，后端转 datetime.date）
        assessment_date = datetime.datetime.strptime(data['assessment_date'], '%Y-%m-%d').date()
        
        # 根据用户角色判断评估类型：患者自评 vs 医生评估
        assessment_type = 2 if current_user.role == 2 else 1
        
        assessment = ScaleAssessment(
            user_id=data['user_id'],
            assessor_id=current_user_id,  # 创建者ID（医生或患者自己）
            assessment_type=assessment_type,  # 新增：评估类型
            assessment_date=assessment_date,
            hamd_total=data['hamd_total'],
            hama_total=data['hama_total'],
            ymrs_total=data['ymrs_total'],
            assessment_notes=data.get('assessment_notes', '')  # 备注可选
        )
        db.session.add(assessment)
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'msg': '评估记录创建成功',
            'data': {'assessment_id': assessment.id}  # 用于后续提交量表详情
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误，需为 YYYY-MM-DD'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'创建失败：{str(e)}'})

# 3.2 医生查询患者的评估记录列表（分页）- 优化版
@app.route('/api/v1/assessments/patient/<int:patient_user_id>', methods=['GET'])
@jwt_required()
def get_patient_assessments(patient_user_id):
    current_user_id = get_jwt_identity()
    current_user = User.query.get(current_user_id)
    
    if not current_user:
        return jsonify({'code': 403, 'msg': '用户不存在'})
    
    # 权限检查：医生可以查看任何患者，患者只能查看自己的
    print(f"=== 后端权限检查调试信息 ===")
    print(f"current_user_id: {current_user_id}")
    print(f"patient_user_id: {patient_user_id}")
    print(f"current_user.role: {current_user.role}")
    
    if current_user.role == 1:  # 医生
        # 验证医生是否绑定了该患者
        is_bound = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == current_user_id,
            DoctorPatientBind.patient_id == patient_user_id,
            DoctorPatientBind.status == 1
        ).first()
        
        if not is_bound:
            return jsonify({'code': 403, 'msg': '未绑定该患者，无法查看其评估记录'})
        
        # 医生可以查看患者的所有评估记录（包括自评和医生评估）
        query = ScaleAssessment.query.filter_by(user_id=patient_user_id)
    elif current_user.role == 2:  # 患者
        # 患者只能查看自己的评估记录（统一转整型避免 '2' 与 2 不相等）
        try:
            if int(current_user_id) != int(patient_user_id):
                print(f"患者ID不匹配: current_user_id={current_user_id}, patient_user_id={patient_user_id}")
                return jsonify({'code': 403, 'msg': '只能查看自己的评估记录'})
        except (TypeError, ValueError):
            return jsonify({'code': 400, 'msg': '无效的用户ID'})
        # 患者查看：查询所有关于自己的记录（包括自评和医生评估）
        query = ScaleAssessment.query.filter_by(user_id=patient_user_id)
    else:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 获取分页参数（默认第1页，每页10条）
    page = request.args.get('page', 1, type=int)
    size = request.args.get('size', 10, type=int)
    
    # 获取筛选参数
    scale_type = request.args.get('scale_type', 'all')  # all, hamd, hama, ymrs
    time_range = request.args.get('time_range', 'all')  # all, week, month, quarter
    
    # 5. 添加时间筛选
    if time_range != 'all':
        from datetime import datetime, timedelta
        now = datetime.now()
        if time_range == 'week':
            week_ago = now - timedelta(days=7)
            query = query.filter(ScaleAssessment.assessment_date >= week_ago.date())
        elif time_range == 'month':
            month_ago = now - timedelta(days=30)
            query = query.filter(ScaleAssessment.assessment_date >= month_ago.date())
        elif time_range == 'quarter':
            quarter_ago = now - timedelta(days=90)
            query = query.filter(ScaleAssessment.assessment_date >= quarter_ago.date())
    
    # 6. 分页查询评估记录（按评估日期倒序）
    assessments = query.order_by(ScaleAssessment.assessment_date.desc()).paginate(page=page, per_page=size)
    
    # 7. 构造返回数据 - 只返回有详细记录的量表
    assessment_list = []
    for ass in assessments.items:
        # 新增：标识评估类型和评估者信息
        assessment_type_name = '患者自评' if ass.assessment_type == 2 else '医生评估'
        
        # 获取评估者信息
        assessor = User.query.get(ass.assessor_id)
        assessor_name = '未知'
        if assessor:
            if ass.assessment_type == 2:
                assessor_name = '患者自评'
            else:
                doctor_info = UserDoctor.query.filter_by(user_id=ass.assessor_id).order_by(UserDoctor.create_time.desc()).first()
                if doctor_info:
                    assessor_name = f"{doctor_info.real_name} 医生"
        
        # 检查哪些量表有详细记录
        has_hamd = ScaleHamd17.query.filter_by(assessment_id=ass.id).first() is not None
        has_hama = ScaleHama.query.filter_by(assessment_id=ass.id).first() is not None
        has_ymrs = ScaleYmrs.query.filter_by(assessment_id=ass.id).first() is not None
        
        # 构建量表数据对象
        scales = {}
        if has_hamd:
            scales['hamd'] = {
                'total': ass.hamd_total,
                'type': '抑郁量表',
                'severity': get_severity_level('hamd', ass.hamd_total)
            }
        if has_hama:
            scales['hama'] = {
                'total': ass.hama_total,
                'type': '焦虑量表',
                'severity': get_severity_level('hama', ass.hama_total)
            }
        if has_ymrs:
            scales['ymrs'] = {
                'total': ass.ymrs_total,
                'type': '躁狂量表',
                'severity': get_severity_level('ymrs', ass.ymrs_total)
            }
        
        # 如果指定了量表类型筛选，只返回包含该量表的评估
        if scale_type != 'all':
            if scale_type == 'hamd' and not has_hamd:
                continue
            elif scale_type == 'hama' and not has_hama:
                continue
            elif scale_type == 'ymrs' and not has_ymrs:
                continue
        
        # 只返回有量表数据的评估
        if scales:
            assessment_list.append({
                'id': ass.id,
                'assessment_id': ass.id,  # 保留原字段名，确保兼容性
                'assessment_date': ass.assessment_date.strftime('%Y-%m-%d'),
                'assessment_type': ass.assessment_type,  # 新增：评估类型 (1=医生评估, 2=患者自评)
                'assessment_type_name': assessment_type_name,  # 新增：评估类型名称
                'assessor_name': assessor_name,  # 新增：评估者姓名
                'scales': scales,  # 新的量表数据结构
                'assessment_notes': ass.assessment_notes,
                'create_time': ass.create_time.strftime('%Y-%m-%d %H:%M:%S'),
                # 保留原有字段，确保向后兼容
                'hamd_total': ass.hamd_total,
                'hamd_status': ass.hamd_status,  # 新增：HAMD完成状态
                'hama_total': ass.hama_total,
                'hama_status': ass.hama_status,  # 新增：HAMA完成状态
                'ymrs_total': ass.ymrs_total,
                'ymrs_status': ass.ymrs_status   # 新增：YMRS完成状态
            })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': len(assessment_list),  # 筛选后的记录数
            'pages': assessments.pages,  # 总页数
            'current_page': page,
            'list': assessment_list
        }
    })

# 新增：医生搜索患者接口（按手机号/姓名）
@app.route('/api/v1/doctor/search-patients', methods=['GET'])
@jwt_required()
def doctor_search_patients():
    doctor_id = get_jwt_identity()
    # 1. 验证当前用户是医生
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 获取前端传递的搜索参数（手机号/姓名，支持模糊搜索姓名）
    search_phone = request.args.get('phone', '')  # 手机号（精确匹配）
    search_name = request.args.get('name', '')    # 姓名（模糊匹配，支持真实姓名/微信昵称）
    
    # 3. 校验搜索参数（至少传递一个搜索条件）
    if not search_phone and not search_name:
        return jsonify({'code': 400, 'msg': '请输入手机号或姓名进行搜索'})
    
    # 4. 构建查询条件：仅搜索角色为患者（role=2）且状态正常（status=1）的用户
    query = User.query.filter(
        User.role == 2,  # 角色为患者
        User.status == 1  # 账号正常
    )
    
    # 5. 按手机号/姓名筛选
    if search_phone:
        query = query.filter(User.phone == search_phone)  # 手机号精确匹配
    if search_name:
        # 姓名模糊匹配（同时匹配真实姓名和微信昵称）
        # 真实姓名存储在 user_patient 表中，需要通过关联查询
        query = query.join(UserPatient, User.id == UserPatient.user_id).filter(
            db.or_(
                UserPatient.real_name.like(f'%{search_name}%'),
                User.wechat_name.like(f'%{search_name}%')
            )
        )
    
    # 6. 执行查询并构造返回数据（关联患者详情表）
    patients = query.all()
    result = []
    for patient in patients:
        # 获取患者的详细信息（年龄、性别等，获取最新的一条记录）
        patient_detail = UserPatient.query.filter_by(user_id=patient.id).order_by(UserPatient.create_time.desc()).first()
        
        # 检查该患者是否已被当前医生绑定
        is_bound = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == doctor_id,
            DoctorPatientBind.patient_id == patient.id,
            DoctorPatientBind.status == 1
        ).first() is not None
        
        # 修改：允许未建档的患者也被返回（用于医生帮忙建档）
        if patient_detail:
            # 已建档的患者
            result.append({
                'patient_id': patient.id,
                'real_name': patient_detail.real_name or patient.wechat_name,
                'phone': patient.phone or '未绑定手机号',
                'gender': '男' if patient_detail.gender == 1 else '女',
                'age': patient_detail.age,
                'avatar': patient.wechat_avatar,
                'is_bound': is_bound,
                'id_card': patient_detail.id_card  # 添加身份证号字段
            })
        else:
            # 未建档的患者（只有微信基础信息）
            result.append({
                'patient_id': patient.id,
                'real_name': patient.wechat_name or '未设置',  # 使用微信昵称
                'phone': patient.phone or '未绑定手机号',
                'gender': None,  # 未建档，性别未知
                'age': None,  # 未建档，年龄未知
                'avatar': patient.wechat_avatar,
                'is_bound': is_bound,
                'id_card': None  # 未建档，无身份证号
            })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': len(result),
            'patients': result
        }
    })

# 新增：医生绑定患者接口
@app.route('/api/v1/doctor/bind-patient', methods=['POST'])
@jwt_required()
def doctor_bind_patient():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证当前用户是医生
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 获取前端传递的患者ID
    patient_id = data.get('patient_id')
    if not patient_id or not isinstance(patient_id, int):
        return jsonify({'code': 400, 'msg': '请选择有效的患者'})
    
    # 3. 验证患者存在且角色为患者（获取最新的一条记录）
    patient = User.query.get(patient_id)
    patient_detail = UserPatient.query.filter_by(user_id=patient_id).order_by(UserPatient.create_time.desc()).first()
    if not patient or patient.role != 2:
        return jsonify({'code': 404, 'msg': '患者不存在或非患者角色'})
    if not patient_detail:
        return jsonify({'code': 400, 'msg': '该患者未完善个人详情，无法绑定'})
    
    # 4. 检查是否已绑定（避免重复绑定）
    existing_bind = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.patient_id == patient_id,
        DoctorPatientBind.status == 1
    ).first()
    if existing_bind:
        return jsonify({'code': 400, 'msg': '已绑定该患者，无需重复操作'})
    
    # 5. 创建绑定关系（若之前解除过绑定，恢复状态而非新增）
    try:
        # 检查是否有已解除的绑定记录，有则恢复，无则新增
        inactive_bind = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == doctor_id,
            DoctorPatientBind.patient_id == patient_id,
            DoctorPatientBind.status == 0
        ).first()
        
        if inactive_bind:
            inactive_bind.status = 1  # 恢复绑定状态
            inactive_bind.bind_time = datetime.datetime.now()  # 更新绑定时间
        else:
            new_bind = DoctorPatientBind(
                doctor_id=doctor_id,
                patient_id=patient_id
            )
            db.session.add(new_bind)
        
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': '患者绑定成功',
            'data': {
                'patient_id': patient_id,
                'patient_name': patient_detail.real_name or patient.wechat_name
            }
        })
    except IntegrityError:
        db.session.rollback()
        return jsonify({'code': 400, 'msg': '绑定失败，请勿重复操作'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'绑定失败：{str(e)}'})

# 优化后的已绑定患者列表接口（合并填表情况）
@app.route('/api/v1/doctor/bound-patients', methods=['GET'])
@jwt_required()
def doctor_get_bound_patients():
    doctor_id = get_jwt_identity()
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    bind_records = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.status == 1
    ).order_by(DoctorPatientBind.bind_time.desc()).all()
    
    bound_patients = []
    for bind in bind_records:
        patient = User.query.get(bind.patient_id)
        # 获取最新的一条患者详细记录
        patient_detail = UserPatient.query.filter_by(user_id=bind.patient_id).order_by(UserPatient.create_time.desc()).first()
        if not patient or not patient_detail:
            continue
        
        # -------------------------- 新增：填表情况统计 --------------------------
        patient_assessments = ScaleAssessment.query.filter_by(
            user_id=bind.patient_id,
            assessor_id=doctor_id  # 仅统计当前医生的评估记录
        ).all()
        completed_scales_detail = []
        hama_completed = False
        hamd17_completed = False
        ymrs_completed = False
        for assessment in patient_assessments:
            if ScaleHama.query.filter_by(assessment_id=assessment.id).first() and '焦虑量表' not in completed_scales_detail:
                hama_completed = True
                completed_scales_detail.append('焦虑量表')
            if ScaleHamd17.query.filter_by(assessment_id=assessment.id).first() and '抑郁量表' not in completed_scales_detail:
                hamd17_completed = True
                completed_scales_detail.append('抑郁量表')
            if ScaleYmrs.query.filter_by(assessment_id=assessment.id).first() and '狂躁量表' not in completed_scales_detail:
                ymrs_completed = True
                completed_scales_detail.append('狂躁量表')
        total_scales = 3
        completed_scales = sum([hama_completed, hamd17_completed, ymrs_completed])
        # -------------------------------------------------------------------
        
        # 获取最新评估日期（原逻辑保留）
        latest_assessment = ScaleAssessment.query.filter(
            ScaleAssessment.user_id == bind.patient_id,
            ScaleAssessment.assessor_id == doctor_id
        ).order_by(ScaleAssessment.assessment_date.desc()).first()
        
        bound_patients.append({
            'patient_id': patient.id,
            'real_name': patient_detail.real_name or patient.wechat_name,
            'phone': patient.phone or '未绑定手机号',
            'gender': '男' if patient_detail.gender == 1 else '女',
            'age': patient_detail.age,
            'avatar': patient.wechat_avatar,
            'bind_time': bind.bind_time.strftime('%Y-%m-%d %H:%M:%S'),
            'latest_assessment_date': latest_assessment.assessment_date.strftime('%Y-%m-%d') if latest_assessment else '暂无评估',
            'latest_assessment_id': latest_assessment.id if latest_assessment else None,  # 添加最新评估ID
            # -------------------------- 新增：填表情况 --------------------------
            'completed_status': f"{completed_scales}/{total_scales}已完成",
            'completed_scales': completed_scales_detail
        })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': len(bound_patients),
            'patients': bound_patients
        }
    })


# ------------------------------
# 4. 量表评估模块 - 细分量表接口（HAMA/HAMD17/YMRS）
# ------------------------------
# 4.1 提交HAMA焦虑量表详情
@app.route('/api/v1/assessments/<int:assessment_id>/hama', methods=['POST'])
@jwt_required()
def submit_hama(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证评估记录归属（确保是当前医生创建的评估）
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment or int(assessment.assessor_id) != int(doctor_id):
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证HAMA所有题目参数（共14题）
    hama_items = [
        'item1_irritability', 'item2_tension', 'item3_fears', 'item4_insomnia',
        'item5_cognition', 'item6_depressed_mood', 'item7_somatic_muscle',
        'item8_somatic_sensory', 'item9_cardiovascular', 'item10_respiratory',
        'item11_gastrointestinal', 'item12_genitourinary', 'item13_autonomic',
        'item14_behavior'
    ]
    for item in hama_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'HAMA题目 {item} 格式错误（需非负整数）'})
    
    # 3. 提交量表数据（若已存在则更新）
    hama_record = ScaleHama.query.filter_by(assessment_id=assessment_id).first()
    try:
        if hama_record:
            # 更新已有记录
            for item in hama_items:
                setattr(hama_record, item, data[item])
        else:
            # 创建新记录
            hama_record = ScaleHama(
                assessment_id=assessment_id,
                **{item: data[item] for item in hama_items}  # 批量传参
            )
            db.session.add(hama_record)
        
        # 新增：更新评估记录的HAMA完成状态
        assessment.hama_status = 1
        
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'HAMA量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.2 提交HAMD17抑郁量表详情（逻辑与HAMA一致，仅题目不同）
@app.route('/api/v1/assessments/<int:assessment_id>/hamd17', methods=['POST'])
@jwt_required()
def submit_hamd17(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 添加调试信息
    print(f"=== HAMD17提交调试 ===")
    print(f"请求的assessment_id: {assessment_id}")
    print(f"当前医生ID: {doctor_id}")
    print(f"当前医生ID类型: {type(doctor_id)}")
    
    # 1. 验证评估归属
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment:
        print(f"评估记录不存在: {assessment_id}")
        return jsonify({'code': 404, 'msg': '评估记录不存在'})
    
    print(f"评估记录详情:")
    print(f"  - 患者ID: {assessment.user_id}")
    print(f"  - 评估医生ID: {assessment.assessor_id}")
    print(f"  - 评估医生ID类型: {type(assessment.assessor_id)}")
    print(f"  - 当前医生ID: {doctor_id}")
    print(f"  - 权限检查: {assessment.assessor_id == doctor_id}")
    print(f"  - 权限检查(字符串): {str(assessment.assessor_id) == str(doctor_id)}")
    
    # 确保类型一致进行比较
    if int(assessment.assessor_id) != int(doctor_id):
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证HAMD17所有题目（共17题）
    hamd17_items = [
        'item1_depression', 'item2_guilt', 'item3_suicide', 'item4_sleep_initial',
        'item5_sleep_middle', 'item6_sleep_late', 'item7_activity', 'item8_retardation',
        'item9_agitation', 'item10_anxiety_psychic', 'item11_anxiety_somatic',
        'item12_somatic_symptoms', 'item13_general_somatic', 'item14_genital',
        'item15_hypochondriasis', 'item16_weight', 'item17_insight'
    ]
    for item in hamd17_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'HAMD17题目 {item} 格式错误'})
    
    # 3. 提交/更新数据
    hamd17_record = ScaleHamd17.query.filter_by(assessment_id=assessment_id).first()
    try:
        if hamd17_record:
            for item in hamd17_items:
                setattr(hamd17_record, item, data[item])
        else:
            hamd17_record = ScaleHamd17(
                assessment_id=assessment_id,
                **{item: data[item] for item in hamd17_items}
            )
            db.session.add(hamd17_record)
        
        # 新增：更新评估记录的HAMD完成状态
        assessment.hamd_status = 1
        
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'HAMD17量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.3 提交YMRS躁狂量表详情
@app.route('/api/v1/assessments/<int:assessment_id>/ymrs', methods=['POST'])
@jwt_required()
def submit_ymrs(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证评估归属
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment or int(assessment.assessor_id) != int(doctor_id):
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证YMRS所有题目（共11题）
    ymrs_items = [
        'item1_mood_elevated', 'item2_activity', 'item3_sleep', 'item4_irritability',
        'item5_speech_rate', 'item6_speech_pressured', 'item7_thought_content',
        'item8_grandiosity', 'item9_distractibility', 'item10_hostility',
        'item11_grandiosity_severity'
    ]
    for item in ymrs_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'YMRS题目 {item} 格式错误'})
    
    # 3. 提交/更新数据
    ymrs_record = ScaleYmrs.query.filter_by(assessment_id=assessment_id).first()
    try:
        if ymrs_record:
            for item in ymrs_items:
                setattr(ymrs_record, item, data[item])
        else:
            ymrs_record = ScaleYmrs(
                assessment_id=assessment_id,
                **{item: data[item] for item in ymrs_items}
            )
            db.session.add(ymrs_record)
        
        # 新增：更新评估记录的YMRS完成状态
        assessment.ymrs_status = 1
        
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'YMRS量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.4 查询指定评估的所有量表详情

@app.route('/api/v1/assessments/<int:assessment_id>/details', methods=['GET'])
@jwt_required()
def get_assessment_details(assessment_id):
    current_user_id = get_jwt_identity()
    current_user = User.query.get(current_user_id)
    
    # 1. 验证权限
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment:
        return jsonify({'code': 404, 'msg': '评估记录不存在'})
    
    # 修改权限逻辑：允许以下情况查看
    # - 医生：创建该评估的医生 OR 绑定了该患者的医生
    # - 患者：评估对象是自己的患者
    has_permission = False
    
    if current_user.role == 1:  # 医生
        # 情况1：医生是评估创建者
        if int(assessment.assessor_id) == int(current_user_id):
            has_permission = True
        # 情况2：医生绑定了该患者
        else:
            is_bound = DoctorPatientBind.query.filter(
                DoctorPatientBind.doctor_id == current_user_id,
                DoctorPatientBind.patient_id == assessment.user_id,
                DoctorPatientBind.status == 1
            ).first()
            if is_bound:
                has_permission = True
    
    elif current_user.role == 2:  # 患者
        # 患者可以查看关于自己的所有评估（自评和医生评估）
        if int(assessment.user_id) == int(current_user_id):
            has_permission = True
    
    if not has_permission:
        return jsonify({'code': 403, 'msg': '无权限查看此评估详情'})

    # 2. 查询各量表数据
    hama = ScaleHama.query.filter_by(assessment_id=assessment_id).first()
    hamd17 = ScaleHamd17.query.filter_by(assessment_id=assessment_id).first()
    ymrs = ScaleYmrs.query.filter_by(assessment_id=assessment_id).first()

    # 3. 模型序列化函数（核心修复）
    def serialize_model(model):
        if not model:
            return {}
        data = {}
        # 只提取数据库表中定义的字段
        for column in model.__table__.columns:
            value = getattr(model, column.name)
            # 处理日期时间类型
            if isinstance(value, (datetime.date, datetime.datetime)):
                data[column.name] = value.strftime('%Y-%m-%d %H:%M:%S')
            else:
                data[column.name] = value
        return data

    # 4. 构造返回数据
    return jsonify({
        'code': 200,
        'data': {
            'assessment': {
                'id': assessment.id,
                'user_id': assessment.user_id,
                'assessment_date': assessment.assessment_date.strftime('%Y-%m-%d'),
                'hamd_total': assessment.hamd_total,
                'hama_total': assessment.hama_total,
                'ymrs_total': assessment.ymrs_total,
                'assessment_notes': assessment.assessment_notes
            },
            'scales': {
                # 修复：使用正确的字段名返回HAMD17答案
                'hamd': [
                    getattr(hamd17, 'item1_depression', 0),
                    getattr(hamd17, 'item2_guilt', 0),
                    getattr(hamd17, 'item3_suicide', 0),
                    getattr(hamd17, 'item4_sleep_initial', 0),
                    getattr(hamd17, 'item5_sleep_middle', 0),
                    getattr(hamd17, 'item6_sleep_late', 0),
                    getattr(hamd17, 'item7_activity', 0),
                    getattr(hamd17, 'item8_retardation', 0),
                    getattr(hamd17, 'item9_agitation', 0),
                    getattr(hamd17, 'item10_anxiety_psychic', 0),
                    getattr(hamd17, 'item11_anxiety_somatic', 0),
                    getattr(hamd17, 'item12_somatic_symptoms', 0),
                    getattr(hamd17, 'item13_general_somatic', 0),
                    getattr(hamd17, 'item14_genital', 0),
                    getattr(hamd17, 'item15_hypochondriasis', 0),
                    getattr(hamd17, 'item16_weight', 0),
                    getattr(hamd17, 'item17_insight', 0)
                ] if hamd17 else [],
                # 修复：使用正确的字段名返回HAMA答案
                'hama': [
                    getattr(hama, 'item1_irritability', 0),
                    getattr(hama, 'item2_tension', 0),
                    getattr(hama, 'item3_fears', 0),
                    getattr(hama, 'item4_insomnia', 0),
                    getattr(hama, 'item5_cognition', 0),
                    getattr(hama, 'item6_depressed_mood', 0),
                    getattr(hama, 'item7_somatic_muscle', 0),
                    getattr(hama, 'item8_somatic_sensory', 0),
                    getattr(hama, 'item9_cardiovascular', 0),
                    getattr(hama, 'item10_respiratory', 0),
                    getattr(hama, 'item11_gastrointestinal', 0),
                    getattr(hama, 'item12_genitourinary', 0),
                    getattr(hama, 'item13_autonomic', 0),
                    getattr(hama, 'item14_behavior', 0)
                ] if hama else [],
                # 修复：使用正确的字段名返回YMRS答案
                'ymrs': [
                    getattr(ymrs, 'item1_mood_elevated', 0),
                    getattr(ymrs, 'item2_activity', 0),
                    getattr(ymrs, 'item3_sleep', 0),
                    getattr(ymrs, 'item4_irritability', 0),
                    getattr(ymrs, 'item5_speech_rate', 0),
                    getattr(ymrs, 'item6_speech_pressured', 0),
                    getattr(ymrs, 'item7_thought_content', 0),
                    getattr(ymrs, 'item8_grandiosity', 0),
                    getattr(ymrs, 'item9_distractibility', 0),
                    getattr(ymrs, 'item10_hostility', 0),
                    getattr(ymrs, 'item11_grandiosity_severity', 0)
                ] if ymrs else []
            }
        }
    })

# ------------------------------
# 5. 统计分析模块
# ------------------------------
# 5.1 医生查询自己的评估总量（按日期范围）
@app.route('/api/v1/statistics/doctor/assessment-count', methods=['GET'])
@jwt_required()
def doctor_assessment_count():
    doctor_id = get_jwt_identity()
    # 1. 验证医生身份
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 获取日期范围参数（默认当月）
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    if not start_date:
        start_date = datetime.datetime.now().replace(day=1).strftime('%Y-%m-%d')  # 当月1号
    if not end_date:
        end_date = datetime.datetime.now().strftime('%Y-%m-%d')  # 当天
    
    # 3. 转换日期格式并查询
    try:
        start = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
        end = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
        
        count = ScaleAssessment.query.filter(
            ScaleAssessment.assessor_id == doctor_id,
            ScaleAssessment.assessment_date >= start,
            ScaleAssessment.assessment_date <= end
        ).count()
        
        return jsonify({
            'code': 200,
            'data': {
                'start_date': start_date,
                'end_date': end_date,
                'assessment_count': count
            }
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误，需为 YYYY-MM-DD'})

# 5.2 管理员查询指定医院的评估总量
@app.route('/api/v1/admin/statistics/hospital/<string:hospital>/count', methods=['GET'])
@jwt_required()
def admin_hospital_count(hospital):
    admin_id = get_jwt_identity()
    # 1. 验证管理员身份
    if not User.query.get(admin_id) or User.query.get(admin_id).role != 3:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 获取日期范围
    start_date = request.args.get('start_date', datetime.datetime.now().replace(day=1).strftime('%Y-%m-%d'))
    end_date = request.args.get('end_date', datetime.datetime.now().strftime('%Y-%m-%d'))
    
    # 3. 关联查询（医院→医生→评估记录）
    try:
        start = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
        end = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
        
        # 子查询：获取指定医院的所有医生ID
        doctor_ids = db.session.query(UserDoctor.user_id).filter(UserDoctor.hospital == hospital).subquery()
        
        # 统计这些医生的评估总量
        count = ScaleAssessment.query.filter(
            ScaleAssessment.assessor_id.in_(doctor_ids),
            ScaleAssessment.assessment_date.between(start, end)
        ).count()
        
        return jsonify({
            'code': 200,
            'data': {
                'hospital': hospital,
                'start_date': start_date,
                'end_date': end_date,
                'total_assessments': count
            }
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误'})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'统计失败：{str(e)}'})

# ------------------------------
# 6. 医生患者绑定管理模块
# ------------------------------
# 6.1 医生解除患者绑定接口
@app.route('/api/v1/doctor/unbind-patient', methods=['POST'])
@jwt_required()
def doctor_unbind_patient():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    patient_id = data.get('patient_id')
    
    # 1. 权限与参数校验
    if not patient_id or not isinstance(patient_id, int):
        return jsonify({'code': 400, 'msg': '请选择有效的患者'})
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 查询绑定记录并解除
    bind_record = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.patient_id == patient_id,
        DoctorPatientBind.status == 1
    ).first()
    if not bind_record:
        return jsonify({'code': 400, 'msg': '未绑定该患者，无需解除'})
    
    try:
        bind_record.status = 0  # 标记为已解除
        db.session.commit()
        return jsonify({'code': 200, 'msg': '患者绑定已解除'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'解除失败：{str(e)}'})


# 严重程度判断函数
def get_severity_level(scale_type, score):
    """
    根据量表类型和分数判断严重程度
    """
    if scale_type == 'hamd':
        if score <= 7:
            return '正常'
        elif score <= 17:
            return '轻度'
        elif score <= 24:
            return '中度'
        else:
            return '重度'
    elif scale_type == 'hama':
        if score <= 7:
            return '正常'
        elif score <= 14:
            return '轻度'
        elif score <= 21:
            return '中度'
        else:
            return '重度'
    elif scale_type == 'ymrs':
        if score <= 12:
            return '正常'
        elif score <= 20:
            return '轻度'
        elif score <= 32:
            return '中度'
        else:
            return '重度'
    else:
        return '未知'


# ==================== PDF导出功能 ====================
import tempfile

@app.route('/api/v1/doctor/export-assessment-pdf/<int:assessment_id>', methods=['GET'])
@jwt_required()
def export_assessment_pdf(assessment_id):
    """导出单次评估的完整量表PDF（三列表格格式）"""
    try:
        # 动态导入PDF生成器，避免影响主程序启动
        from pdf_generator_table import TableStylePDFGenerator
        
        current_user_id = get_jwt_identity()
        
        # 验证是否是医生
        doctor = UserDoctor.query.filter_by(user_id=current_user_id).first()
        if not doctor:
            return jsonify({'code': 403, 'msg': '仅医生可以导出患者报告'}), 403
        
        # 获取评估记录
        assessment = ScaleAssessment.query.get(assessment_id)
        if not assessment:
            return jsonify({'code': 404, 'msg': '评估记录不存在'}), 404
        
        # 验证医生是否有权限访问该患者
        binding = DoctorPatientBind.query.filter_by(
            doctor_id=current_user_id,
            patient_id=assessment.user_id
        ).first()
        
        if not binding:
            return jsonify({'code': 403, 'msg': '无权访问该患者信息'}), 403
        
        # 获取患者信息
        patient_user = User.query.get(assessment.user_id)
        if not patient_user:
            return jsonify({'code': 404, 'msg': '患者不存在'}), 404
        
        patient = UserPatient.query.filter_by(user_id=assessment.user_id).first()
        
        patient_info = {
            'real_name': (patient.real_name if patient else None) or patient_user.wechat_name or '未知',
            'gender': patient.gender if patient else 0,
            'age': patient.age if patient else 0,
            'phone': patient_user.phone or '未提供'
        }
        
        # 获取评估者信息
        assessor_name = '未知'
        if assessment.assessor_id:
            assessor = User.query.get(assessment.assessor_id)
            if assessor:
                # 尝试从医生表获取姓名
                doctor_info = UserDoctor.query.filter_by(user_id=assessment.assessor_id).first()
                assessor_name = (doctor_info.real_name if doctor_info else None) or assessor.wechat_name or '未知'
        
        # 构建评估数据
        assessment_data = {
            'assessment_date': assessment.assessment_date.strftime('%Y-%m-%d') if assessment.assessment_date else '',
            'create_time': assessment.create_time.strftime('%H:%M') if assessment.create_time else '',
            'assessment_type_name': '医生评估' if assessment.assessment_type == 1 else '患者自评',
            'assessor_name': assessor_name,
            'hamd_status': assessment.hamd_status,
            'hamd_total': assessment.hamd_total or 0,
            'hama_status': assessment.hama_status,
            'hama_total': assessment.hama_total or 0,
            'ymrs_status': assessment.ymrs_status,
            'ymrs_total': assessment.ymrs_total or 0
        }
        
        # 获取详细评分
        if assessment.hamd_status == 1:
            hamd_detail = ScaleHamd17.query.filter_by(assessment_id=assessment_id).first()
            if hamd_detail:
                assessment_data['hamd_details'] = [
                    hamd_detail.item1_depression, hamd_detail.item2_guilt, hamd_detail.item3_suicide,
                    hamd_detail.item4_sleep_initial, hamd_detail.item5_sleep_middle,
                    hamd_detail.item6_sleep_late, hamd_detail.item7_activity, hamd_detail.item8_retardation,
                    hamd_detail.item9_agitation, hamd_detail.item10_anxiety_psychic,
                    hamd_detail.item11_anxiety_somatic, hamd_detail.item12_somatic_symptoms,
                    hamd_detail.item13_general_somatic, hamd_detail.item14_genital,
                    hamd_detail.item15_hypochondriasis, hamd_detail.item16_weight,
                    hamd_detail.item17_insight
                ]
        
        if assessment.hama_status == 1:
            hama_detail = ScaleHama.query.filter_by(assessment_id=assessment_id).first()
            if hama_detail:
                assessment_data['hama_details'] = [
                    hama_detail.item1_irritability, hama_detail.item2_tension, hama_detail.item3_fears,
                    hama_detail.item4_insomnia, hama_detail.item5_cognition,
                    hama_detail.item6_depressed_mood, hama_detail.item7_somatic_muscle,
                    hama_detail.item8_somatic_sensory, hama_detail.item9_cardiovascular,
                    hama_detail.item10_respiratory, hama_detail.item11_gastrointestinal,
                    hama_detail.item12_genitourinary, hama_detail.item13_autonomic,
                    hama_detail.item14_behavior
                ]
        
        if assessment.ymrs_status == 1:
            ymrs_detail = ScaleYmrs.query.filter_by(assessment_id=assessment_id).first()
            if ymrs_detail:
                assessment_data['ymrs_details'] = [
                    ymrs_detail.item1_mood_elevated, ymrs_detail.item2_activity, ymrs_detail.item3_sleep,
                    ymrs_detail.item4_irritability, ymrs_detail.item5_speech_rate, ymrs_detail.item6_speech_pressured,
                    ymrs_detail.item7_thought_content, ymrs_detail.item8_grandiosity, ymrs_detail.item9_distractibility,
                    ymrs_detail.item10_hostility, ymrs_detail.item11_grandiosity_severity
                ]
        
        # 生成PDF
        generator = TableStylePDFGenerator()
        
        # 创建临时文件
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf')
        pdf_path = temp_file.name
        temp_file.close()
        
        generator.generate_patient_report(patient_info, assessment_data, pdf_path)
        
        # 返回PDF文件
        filename = f"{patient_info['real_name']}_评估报告_{assessment.assessment_date.strftime('%Y%m%d')}.pdf"
        
        return send_file(
            pdf_path,
            mimetype='application/pdf',
            as_attachment=True,
            download_name=filename
        )
        
    except Exception as e:
        print(f"导出PDF失败: {str(e)}")
        import traceback
        traceback.print_exc()
        return jsonify({'code': 500, 'msg': f'导出失败: {str(e)}'}), 500


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)  # 开发环境开启debug便于调试
